package org.wcms.surrounded.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.wcms.surrounded.Constants;
import org.wcms.surrounded.model.User;
import org.wcms.surrounded.persistence.RecordService;
import org.wcms.surrounded.persistence.UserService;
import org.wcms.surrounded.utils.Utils;
import org.wcms.surrounded.web.data.AddScoreData;
import org.wcms.surrounded.web.data.ResponseData;

import com.google.inject.Inject;
import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.Parameter;
import com.restfb.exception.FacebookException;
import com.restfb.types.FacebookType;

public class AddScoreAjaxHandler implements AjaxHandler {

    private final RecordService recordService;
    private final UserService userService;
    
    @Inject
    public AddScoreAjaxHandler(UserService userService, RecordService recordService) {
        this.userService = userService;
        this.recordService = recordService;
    }
    
    @Override
    public ResponseData handle(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        
        AddScoreData updateScoreData = new AddScoreData();
        updateScoreData.setScoreAdded(false);
        updateScoreData.setUsernameOvertaken(false);
        
        User user = (User)req.getSession().getAttribute(Constants.SURROUNDED_SESSION_USER);
        if (user.getId() == Constants.SURROUNDED_NEW_USER_ID) {
            return updateScoreData;
        }
        
        // test if username was overtaken
        if (!user.isRegistered() &&
             userService.getUserById(user.getId()) == null) {
            
    		updateScoreData.setUsernameOvertaken(true);
    		
    		user = userService.getUserById(Constants.SURROUNDED_NEW_USER_ID);        		
    		Utils.updateUserSessionAndCookie(req, resp, user);
    		
    		return updateScoreData;
        }
        	
        
        String rawScore = req.getParameter(Constants.SURROUNDED_SCORE_KEY);
        if (rawScore == null) {
            return updateScoreData;
        }
        
        int score;
        try {
            score = Integer.parseInt(rawScore);
        } catch (NumberFormatException e) {
            return updateScoreData;
        }
        
        if (score <= 0) {
            return updateScoreData;
        }
        
        recordService.addRecord(user, score);
        
        updateScoreData.setScoreAdded(true);
        
        if (user.getScore() < score) {
            
            Integer oldScore = user.getScore();
            
            user.setScore(score);            
            userService.updateUser(user);
            
            updateUserScoreInOpenGraph(user, oldScore);
            
            // only send notification when some user breaks his own record
            sendScoreNotifications(user);
        }
        
        updateScoreData.setCurrentBestScore(user.getScore());
        
        return updateScoreData;
    }

    private void sendScoreNotifications(User cause) {

        Iterable<User> users = userService.getUsersWithLowerScore(cause);
        
        String message = "Your Surrounded record was broken by " + cause.getUserName() + " who scored " + cause.getScore()
        				 + ". Play again and attempt to break his record!";
        
        for (User user : users) {
            
            if (user.isRegistered()) {
            
                FacebookClient facebook = new DefaultFacebookClient(user.getAccessToken());
                try {
                	facebook.publish("me/feed", FacebookType.class, Parameter.with("message", message));
                }
                catch(FacebookException fe) {
                	//TODO: nothing, really.
                }                
            }
        }
        
    }
    
    private void updateUserScoreInOpenGraph(User user, Integer oldScore) {
        if (user.isRegistered()) {
            FacebookClient facebook = new DefaultFacebookClient(user.getAccessToken());
            try {
                facebook.publish("me/games.high_score", FacebookType.class, 
                        Parameter.with("new_high_score", String.valueOf(user.getScore())),
                        Parameter.with("old_high_score", String.valueOf(oldScore)),
                        Parameter.with("game", "http://surroundedgame.appspot.com/")
                );
            } catch (FacebookException e) {
                // Oh well..
            }
            
        }
    }
    
}
